package IceAssembly;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/**
 * This class reads the tables(MOT, POT & ERRORTABLE) and also returns the table related
 * parameter needed by other classes.<p>
 * <u>Member Variables:</u><br>
 *  mot_string : static private String[][]<br>
 *  pot_string : static private String[][]<br>
 *  error_string : static private String[][]<br>
 * Creation Date : April 12,2008
 * <p>
<b>Original Author:</b> Yogesh Jindal
<p>
 */

public class Initialize{
        
    static private String[][] mot_string;   
    static private String[][] pot_string;   
    static private String[][] error_string;   
    /**
     * Default constructor - Initializes the MOT, POT and ERRORTABLE string by calling their respective functions.
     */
    public Initialize(){
        iniErrorTable();
        iniMot(); 
        iniPot(); 
    }
    
    /**
     * This function will return the num of columns in the file(.csv file)passed 
     * if the first input parameter is 0 and will return the num of rows if the
     * input parameter is 1.<p>
     * Change Log:<br>
     *  April 18,2008- Changed some variable names - Yogesh Jindal<br>
     *  April 18,2008- Added the documentation - Yogesh Jindal<p>
     * <p>
<b>Original Author:</b> Yogesh Jindal
<p>
     * @param value  decides whether to return number of columns or number of rows.
     * @param file  File instance for the URL.
     * @return will return an integer; which is either number of columns or number of rows.
    **/
    static private int getXOrYExcelFile(int value, File file){
        if(value==0){
            try{
                BufferedReader buffer_reader = new BufferedReader(new FileReader(file));
                buffer_reader.readLine();
                String mot_excel_line=buffer_reader.readLine();//string to save a row of excel...
                int no_words=1;
                for(int loop=0; loop<mot_excel_line.length(); loop++){
                    if(mot_excel_line.charAt(loop)==','){
                        no_words++;
                    }
                } 
                return no_words;
            }catch(IOException e){
                return -1;
            }
        }
        if(value==1){
            try{
                BufferedReader buffer_reader = new BufferedReader(new FileReader(file));
                int no_lines=-1;
                while(buffer_reader.readLine()!=null){
                    no_lines++;
                }
                return no_lines;
            }catch(IOException e){
                return -1;
            }
        }
        return -1;
    }
    
        /**
     * This function will return the number of columns in the file passed a filename
     * passed if the first input parameter is 0 and will return the num of rows if the
     * input parameter is 1.<p>
     * Change Log:<br>
     *  April 18,2008- Changed some variable names - Yogesh Jindal<br>
     *  April 18,2008- Added the documentation - Yogesh Jindal
     *  May 10, 2008 - Made additional version of operation that allows you to choose the separator char - Peter Dietz <br>
     * @author Yogesh Jindal
     * @param value  decides whether to return number of columns or number of rows.
     * @param file  File instance for the URL.
     * @param separator The character used to delimit fields in the file.
     * @return will return an integer; which is either number of columns or number of rows.
    **/
    static private int getXOrYExcelFile(int value, File file, char separator){
        if(value==0){
            try{
                BufferedReader buffer_reader = new BufferedReader(new FileReader(file));
                buffer_reader.readLine();
                String mot_excel_line=buffer_reader.readLine();//string to save a row of excel...
                int no_words=1;
                for(int loop=0; loop<mot_excel_line.length(); loop++){
                    if(mot_excel_line.charAt(loop)==separator){
                        no_words++;
                    }
                } 
                return no_words;
            }catch(IOException e){
                return -1;
            }
        }
        if(value==1){
            try{
                BufferedReader buffer_reader = new BufferedReader(new FileReader(file));
                int no_lines=-1;
                while(buffer_reader.readLine()!=null){
                    no_lines++;
                }
                return no_lines;
            }catch(IOException e){
                return -1;
            }
        }
        return -1;
    }    
    
    /**
     * This function will take a line of .csv file and the number of columns in that line 
     * as input and will return a string array that contains all the columns in that line.
     * The columns are separated by commas in the input string.<p>
     * Change Log:<br>
     *  April 18,2008- Added the documentation - Yogesh Jindal<br>
     * <p>
<b>Original Author:</b> Yogesh Jindal
<p>
     * @param excel_line - A line of .csv file
     * @param no_column  number of columns in that line.
     * @return Returns a String array which contains the columns of input String.     
    **/
    static private String[] getStringArrayFromExcelFormatString(String excel_line, int no_column){           
        String[] words_array = new String[no_column]; int index=0; int count=0;                
        for(int loop=0; loop<excel_line.length(); loop++){
            if(excel_line.charAt(loop)==','){                 
                words_array[count]=excel_line.substring(index,loop); count++;
                index=loop+1;
            }
        }       
        words_array[count]=excel_line.substring(index,excel_line.length());        
        return(words_array);        
    }
    
    /**
     * This function will take a line of .csv file and the number of columns in that line 
     * as input and will return a string array that contains all the columns in that line.
     * The columns are separated by commas in the input string.<p>
     * Change Log:<br>
     *  April 18,2008- Added the documentation - Yogesh Jindal<br>
     * May 10, 2008 - Fixed to accept a separator character.<br>
     * @author Yogesh Jindal
     * @param excel_line - A line of .csv file
     * @param no_column  number of columns in that line.
     * @param separator Character to delimit the field
     * @return Returns a String array which contains the columns of input String.     
    **/
    static private String[] getStringArrayFromExcelFormatString(String excel_line, int no_column, char separator){           
        String[] words_array = new String[no_column]; int index=0; int count=0;                
        for(int loop=0; loop<excel_line.length(); loop++){
            if(excel_line.charAt(loop)==separator){                 
                words_array[count]=excel_line.substring(index,loop); count++;
                index=loop+1;
            }
        }       
        words_array[count]=excel_line.substring(index,excel_line.length());        
        return(words_array);        
    }
    
    /**
     * This functions initializes the mot_string[][]. It uses the URL of the Machine
     * Operation Table which is defined and initialized in Interface.java.<p>
     * Change Log:<br>
     *  April 18,2008- Added the Documentation and return type - Yogesh Jindal<br>
     *  April 18,2008- Changed the IOException message - Yogesh Jindal<br>
     * 
     * <p><b>Original Author:</b>  Yogesh Jindal
     * 
     * @return Returns 1 if successful else 0.
    **/
    private int iniMot () {
        File file_address = new File(Control.link_mot);        
        //System.out.println(file_address.getAbsolutePath());
        try{
            BufferedReader buffer_reader = new BufferedReader(new FileReader(file_address));
            String mot_excel_line;//string to save a row of excel... 
            buffer_reader.readLine();//shift bufferreader to next line...
            mot_string = new String[getXOrYExcelFile(1, file_address)][getXOrYExcelFile(0, file_address)];
            int count=0;
            while((mot_excel_line = buffer_reader.readLine())!=null){
                String[] temp= getStringArrayFromExcelFormatString(mot_excel_line,getXOrYExcelFile(0, file_address));
                for(int loop1=0; loop1<temp.length; loop1++){
                    mot_string[count][loop1] = temp[loop1];
                } count++;
            }           
        }catch(IOException e){
            System.out.println("exception in reading Machine Operation Table");
            return 0;
        }
      return 1;
    }

    /**
     * This functions initializes the pot_string[][]. It uses the URL of the Psuedo-op
     * Table which is defined and initialized in Interface.java.<p>
     * Change Log:<br>
     *  April 18,2008- Added the Documentation and return type - Yogesh Jindal<br>
     *  April 18,2008- Changed the IOException message -  Yogesh Jindal<br>
     * <p><b>Original Author:</b>  Yogesh Jindal
     * 
     * @return Returns 1 if successful else 0.
    **/
    private int iniPot () {
        File file_address = new File(Control.link_pot);
        try{
            BufferedReader buffer_reader = new BufferedReader(new FileReader(file_address));
            String pot_excel_line;//string to save a row of excel... 
            buffer_reader.readLine();//shift bufferreader to next line...
            pot_string = new String[getXOrYExcelFile(1, file_address)][getXOrYExcelFile(0, file_address)];
            int count=0;
            while((pot_excel_line = buffer_reader.readLine())!=null){
                String[] temp= getStringArrayFromExcelFormatString(pot_excel_line,getXOrYExcelFile(0, file_address));
                for(int loop=0; loop<temp.length; loop++){
                    pot_string[count][loop] = temp[loop];
                } count++;
            }            
        }catch(IOException e){
            System.out.println("exception in reading Pseudo-Op Table");            
            return 0;
        }        
      return 1;  
    }

    /**
     * This functions initializes the error_string[][]. It uses the URL of the Error
     * Table which is defined and initialized in Interface.java.<p>
     * Change Log:<br>
     *  April 18,2008 - Added the Documentation and return type - Yogesh Jindal<br>
     *  April 18,2008 - Changed the IOException message - Yogesh Jindal<br>
     *  April 22,2008 - Changed the function name from iniError to iniErrorTable<br>
     * <p><b>Original Author:</b>  Yogesh Jindal   
     * @return Returns 1 if successful else 0.
    **/
    private int iniErrorTable () {
        File file_address = new File(Control.link_errortable);
        //System.out.println(file_address.getAbsolutePath());
        try{
            BufferedReader buffer_reader = new BufferedReader(new FileReader(file_address));
            String mot_excel_line;//string to save a row of excel... 
            buffer_reader.readLine();//shift bufferreader to next line...
            error_string = new String[getXOrYExcelFile(1, file_address, '|')][getXOrYExcelFile(0, file_address, '|')];            
            int count=0;
            while((mot_excel_line = buffer_reader.readLine())!=null){
                String[] temp= getStringArrayFromExcelFormatString(mot_excel_line,getXOrYExcelFile(0, file_address,'|'),'|');
                for(int loop1=0; loop1<temp.length; loop1++){
                    error_string[count][loop1] = temp[loop1];
                } count++;
            }            
        }catch(IOException e){
            System.out.println("exception in reading error table");            
            return 0;
        }
      return 1;
    }

    /**
     * This function returns the contents of a column as a string array whose number is passed as
     * first input for the table name(MOT, POT or ERRORTABLE) which the second input.<br>
     * If table name or column number are invalid then returns the string array of length 1
     * with "null" in it.<p>
     * Change Log:<br>
     *  April 18,2008 - Added the documentation and modified some printing error statements - Yogesh Jindal<br>
     *  April 18,2008 - Modified the returned string for any error - Yogesh Jindal<p>
     *  April 22,2008 - Changing some print statements and documentation- Yogesh Jindal<br>
     *  April 22,2008 - Modified Returned string for error cases - Yogesh Jindal<br>
     * <p><b>Original Author:</b>  Yogesh Jindal
     * @param column_num - The column number to read. 
     * @param table - The table to read which is MOT, POT or ERRORTABLE.  
     * @return String[] - Returns a column of a table as a string array.  
    **/ 
    protected String[] readColumn (int column_num, String table) {
        String err_ret_string[] = new String[1]; err_ret_string[0]="null";
        if(table.compareTo("MOT")==0){
            if(column_num>=mot_string[1].length || column_num<0){
                System.out.println("No Such Column Exists in MOT");                
                return err_ret_string;
            }else{
                String[] S = new String[mot_string.length];
                for(int loop=0; loop<S.length; loop++){
                    S[loop] = mot_string[loop][column_num];
                }
                return S;
            }
        }
        if(table.compareTo("POT")==0){
            if(column_num>=pot_string[1].length || column_num<0){
                System.out.println("No Such Column Exists in POT");
                return err_ret_string;
            }else{
                String[] S = new String[pot_string.length];
                for(int loop=0; loop<S.length; loop++){
                    S[loop] = pot_string[loop][column_num];
                }
                return S;
            }
        }
        if(table.compareTo("ERRORTABLE")==0){
            if(column_num>=error_string[1].length || column_num<0){
                System.out.println("No Such Column Exists in ErrorTable");
                return err_ret_string;
            }else{
                String[] S = new String[error_string.length];
                for(int loop=0; loop<S.length; loop++){
                    S[loop] = error_string[loop][column_num];
                }
                return S;
            }
        }
        System.out.println("Incorrect Table Name");
        return err_ret_string;
    }
    
    /**
     * This function returns a string array which contains all the functions
     * for the mnemonic passed as input.<br>
     * Change Log:<br>
     *  April 18,2008 - Initial code entry - Yogesh Jindal<br>
     *  April 22,2008 - Changing some documentation - Yogesh Jindal<br>
     * <p><b>Original Author:</b>  Yogesh Jindal
     * @param mnemonic  A valid mnemonic
     * @return Returns the String array of functions of the passed mnemonic.
    */    
    private String[] getFunForOp (String mnemonic) {
        int count=0;
        for(int index=0; index< mot_string.length; index++){
            if(mot_string[index][0].compareTo(mnemonic)==0){
                count++;
            }
        }
        String[] fun_string = new String[count]; count=0;
        for(int index=0; index< mot_string.length; index++){
            if(mot_string[index][0].compareTo(mnemonic)==0){
                fun_string[count] = mot_string[index][1];
                count++;
            }
        }
        return fun_string;
    }
       
    /**
     * This function returns the parameters of a mnemonic and function pair.<br>
     * If an invalid pair then returns a string array of length 4:<br>
     *  Index 0 = "0"<br>
     *  Index 1 = "null"<br>
     *  Index 2 = "null"<br>
     *  Index 3 = "null"<br>
     * If a valid pair then returns a string array of length 4:<br>
     *  Index 0 = "1"<br>
     *  Index 1 = 5 bit binary code<br>
     *  Index 2 = operand format code<br>
     *  Index 3 = relocation type<P>
     * Change Log:<br>
     *  April 18,2008 - Initial code entry - Yogesh Jindal<br>
     *  April 22,2008 - Changing some documentation - Yogesh Jindal<br>
     * <p><b>Original Author:</b>  Yogesh Jindal
     * @param mnemonic  A mnemonic.
     * @param  fun  A function.
     * @return Returns the line parameters string array for a mnemonic, function pair.
    **/
    protected String[] getInfoForMnemonicPair(String mnemonic, String fun){
        String[] line_param = new String[4]; int isvalid=0;
        for(int index=0; index<mot_string.length; index++){
            if(mot_string[index][0].compareTo(mnemonic.toUpperCase())==0){
                if(mot_string[index][1].compareTo(fun.toUpperCase())==0){
                    line_param[0]="1"; isvalid=1;
                    line_param[1]=mot_string[index][2];
                    line_param[2]=mot_string[index][3];
                    line_param[3]=mot_string[index][4];
                    break;
                }
            }
        }
        if(isvalid==0){ line_param[0]="0"; line_param[1]="null"; line_param[2]="null"; line_param[3]="null"; }
        return line_param;
    }
    
    /**
     * This function returns the parameters of a directive.<br>
     * If an invalid pair then returns a string array of length 4:<br>
     *  Index 0 = "0"<br>
     *  Index 1 = "null"<br>
     *  Index 2 = "null"<br>
     *  Index 3 = "null"<br>
     * If a valid pair then returns a string array of length 4:<br>
     *  Index 0 = "1"<br>
     *  Index 1 = length,<br>
     *  Index 2 = operand format,<br>
     *  Index 3 = label_no.<p>
     * Change Log:<br>
     *  April 18,2008 - Initial code entry - Yogesh Jindal<br>
     *  April 22,2008 - Changing some documentation - Yogesh Jindal<br>
     * <p><b>Original Author:</b>  Yogesh Jindal
     * @param pseudo A pseudo OP.     
     * @return Returns the line parameters string array.
    **/
    protected String[] getInfoForPseudoOp(String pseudo){
        String[] line_param = new String[4]; int isvalid=0;
        for(int index=0; index<pot_string.length; index++){
            if(pot_string[index][0].compareTo(pseudo.toUpperCase())==0){               
                    line_param[0]="1"; isvalid=1;
                    line_param[1]=pot_string[index][1];
                    line_param[2]=pot_string[index][2];
                    line_param[3]=pot_string[index][3];
                    break;                
            }
        }
        if(isvalid==0){ line_param[0]="0"; line_param[1]="null"; line_param[2]="null"; line_param[3]="null"; }
        return line_param;        
    }
    
    /**
    * This function will return the string for an error message to be produced.  The error numbers are loaded when 
     * one is detected and this function will aid in the production of a valid error message for the user to understand.
    * <p>
    * <b>Change Log:</b><br>
    * 5/4/08 - Initial Code Entry - Yogesh Jindal <br>
      * 5/5/08 - Inserted Documentation - Keith Hill <br>
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * None <br>
    * <p>
    * <b>Date of module being installed:</b> 5/4/08
    * <p><b>Original Author:</b>  <original author>
    * @param code This is the error code that has been inserted into the error table.
    * @return The function will return the corosponding string assocaiated with the error number.  If the error number does not match, null will be returned.
    */
    protected String getStringForCode(String code){
        System.out.println(error_string[0][1]);
        for(int index=0; index<error_string.length; index++){
            if(error_string[index][0].contentEquals(code)){                
                return error_string[index][1];
            }
        }
        return "null";
    }

    /**
     * Finds the error message associated with the error code, for user information
    * <b>Change Log:</b><br>
    * 05/10/08 - Initial Code - Peter Dietz<br>
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * If error was not defined it will let you know.<br>
    * <p>
    * <b>Date of module being installed:</b> 05/10/2008
    * @author Peter
     * @param error_code String representing an integer 000's are fatal 100's are severe 200's are warning
     * @return 2 element array with the error message and the suggested way to fix it.
     */
    public String[] getErrorMessage(String error_code){
        iniErrorTable();
        String[] error_message = new String[2];
        error_message[0] = "Undefined Error Code";
        error_message[1] = "Define Error Code";
        for (int i=0; i<error_string.length; i++){
            if(error_string[i][0].startsWith(error_code)){
                error_message[0] = error_string[i][1];
                error_message[1] = error_string[i][2];
            }
        }
        return error_message;
    }
    
    /**
    * Will print the given error to the screen
    * <p>
    * <b>Change Log:</b><br>
    * 05/24/2008 - Initial Code - Peter Dietz<br>
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * none yet<br>
    * <p>
    * <b>Date of module being installed:</b> 05/24/2008
    * <p><b>Original Author:</b>  Peter Dietz
    * @param error_code String representing integer of the error code
    */
    public void printErrorMessage(String error_code){
        Initialize initialize_instance = new Initialize();
        String[] error_message = initialize_instance.getErrorMessage(error_code);
        System.out.println("ERROR("+error_code+"): "+error_message[0]);
        System.out.println("SUGGESTED FIX: "+error_message[1]);
    }
    
   /**
    * Will print the given error to the screen
    * <p>
    * <b>Change Log:</b><br>
    * 05/24/2008 - Initial Code - Peter Dietz<br>
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * none yet<br>
    * <p>
    * <b>Date of module being installed:</b> 05/24/2008
    * <p><b>Original Author:</b>  Peter Dietz
    * @param error_number Integer of the error code
    */
    public void printErrorMessage(int error_number){
        printErrorMessage(String.valueOf(error_number));
    }
}
